package smallfrench.moteur.noeuds;

import smallfrench.moteur.biblio.RBooleen;
import smallfrench.moteur.biblio.RClasse;
import smallfrench.moteur.biblio.err.ErreurClasse;
import smallfrench.moteur.biblio.err.ErreurRien;
import smallfrench.moteur.biblio.err.ExceptionInterruption;
import smallfrench.moteur.interp.Portee;
import smallfrench.moteur.interp.RObjet;
import smallfrench.moteur.interp.err.ExceptionSortieBoucle;
import smallfrench.moteur.interp.err.RException;
import smallfrench.moteur.lexer.lexemes.Lexeme;

/**
 * Boucle "tantque" "(" condition ")" ...
 * @author antoine1023
 *
 */
public class NTantque extends Noeud {

	Noeud noeudCondition;
	Noeud noeudRepetition;

	public NTantque(Lexeme t, Noeud noeudCondition, Noeud noeudRepetition) {
		super(t);
		this.noeudCondition = noeudCondition;
		this.noeudRepetition = noeudRepetition;
	}

	@Override
	public RObjet evaluer(Portee pile) {
		RObjet condition;
		for (;;) {

			/* Pour éviter les boucles infinies, on regarde si le thread a
			 * été interrompu par l'utilisateur. */
			if (Thread.interrupted())
				throw new RException(new ExceptionInterruption());

			condition = noeudCondition.evaluer(pile);
			if (condition == null)
				throw ErreurRien.nouvelleException(lexeme.debut);

			if (! (condition instanceof RBooleen))

				throw ErreurClasse.nouvelleException(
						noeudCondition.lexeme.debut,
						condition,
						RClasse.CLASSE);

			boolean bCond = ((RBooleen)condition).valeur;
			if (!bCond)
				return null;

			try {
				noeudRepetition.evaluer(pile);
			} catch (ExceptionSortieBoucle t) {
				return null;
			}
		}
	}

	@Override
	public String toString() {
		return "tantque (" + noeudCondition + ") " + noeudRepetition;
	}

}
